package com.hyjiacan.apps.audionly.utils

import android.content.Context
import android.media.MediaCodec
import android.media.MediaFormat
import android.media.MediaMuxer
import android.net.Uri
import android.util.Log
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.audio.AudioAttributes
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.audio.AudioSink
import androidx.media3.exoplayer.audio.DefaultAudioSink
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
import androidx.media3.exoplayer.upstream.DataSource
import androidx.media3.exoplayer.upstream.DefaultDataSourceFactory
import androidx.media3.exoplayer.upstream.DataSpec
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import java.io.File
import java.nio.ByteBuffer
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

// Media3部分API标记为不稳定，生产环境需注意版本兼容性
@UnstableApi 
class ExoAudioExtractor(private val context: Context) {
    private val TAG = "ExoAudioExtractor"
    private var exoPlayer: ExoPlayer? = null
    private var mediaMuxer: MediaMuxer? = null
    private var audioTrackIndex = -1
    private var isCancelled = false
    private var progressJob: Job? = null
    private var audioFormat: MediaFormat? = null

    /**
     * 支持的音频输出格式
     */
    enum class OutputFormat(
        val mimeType: String,
        val fileExtension: String,
        val muxerOutputFormat: Int
    ) {
        AAC("audio/mp4a-latm", "aac", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4),
        MP3("audio/mpeg", "mp3", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4),
        WAV("audio/x-wav", "wav", MediaMuxer.OutputFormat.MUXER_OUTPUT_PCM_16BIT),
        FLAC("audio/flac", "flac", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4),
        OGG("audio/ogg", "ogg", MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG),
        M4A("audio/mp4", "m4a", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4),
    }

    /**
     * 提取音频并实时反馈进度
     */
    fun extractAudio(
        inputPath: String,
        outputDir: String,
        outputFormat: OutputFormat,
        scope: CoroutineScope,
        progressListener: (Int) -> Unit,
        completionListener: (Boolean, String) -> Unit
    ) {
        val inputFile = File(inputPath)
        if (!inputFile.exists()) {
            scope.launch(Dispatchers.Main) {
                completionListener(false, "输入文件不存在: $inputPath")
            }
            return
        }

        val outputPath = "$outputDir/${inputFile.nameWithoutExtension}.${outputFormat.fileExtension}"
        val outputFile = File(outputPath)
        if (outputFile.exists()) outputFile.delete()
        File(outputDir).mkdirs()

        scope.launch(Dispatchers.IO) {
            try {
                // 1. 配置轨道选择器（仅保留音频）
                val trackSelector = DefaultTrackSelector(context).apply {
                    setParameters(
                        buildUponParameters()
                            .setExcludedTrackTypes(
                                intArrayOf(
                                    C.TRACK_TYPE_VIDEO,
                                    C.TRACK_TYPE_TEXT,
                                    C.TRACK_TYPE_METADATA
                                )
                            )
                    )
                }

                // 2. 配置音频输出接收器（捕获解码后的数据）
                val audioSink = DefaultAudioSink.Builder(context)
                    .setAudioAttributes(AudioAttributes.Builder().build(), C.AUDIO_SESSION_ID_UNSET)
                    .setAudioProcessorChain(DefaultAudioSink.DEFAULT_AUDIO_PROCESSOR_CHAIN)
                    .setOffloadModeEnabled(false)
                    .build()
                    // 正确实现AudioSink监听器
                    .setListener(object : AudioSink.Listener {
                        override fun onUnderrun(bufferSize: Int, bufferSizeMs: Long, elapsedSinceLastFeedMs: Long) {
                            Log.d(TAG, "音频缓冲区不足: bufferSize=$bufferSize, bufferSizeMs=$bufferSizeMs")
                        }
                        override fun onPositionDiscontinuity(reason: Int) {}
                        override fun onFlush() {
                            mediaMuxer?.stop()
                        }
                        override fun onBufferAvailable(buffer: ByteBuffer, offset: Int, size: Int, presentationTimeUs: Long) {
                            if (isCancelled || audioTrackIndex == -1 || mediaMuxer == null) {
                                return
                            }
                            try {
                                val bufferInfo = MediaCodec.BufferInfo()
                                bufferInfo.size = buffer.remaining()
                                bufferInfo.presentationTimeUs = exoPlayer?.currentPosition?.times(1000) ?: 0
                                bufferInfo.flags = 0
                                // 调整position和limit以确保正确写入数据
                                buffer.position(offset)
                                buffer.limit(offset + size)
                                mediaMuxer?.writeSampleData(audioTrackIndex, buffer, bufferInfo)
                            } catch (e: Exception) {
                                Log.e(TAG, "写入音频数据失败", e)
                            }
                        }
                    })

                        // 移除可能不存在的方法
                        // override fun onEndOfStream() {
                        //     scope.launch(Dispatchers.Main) {
                        //         progressListener(100)
                        //         completionListener(true, "提取成功: $outputPath")
                        //     }
                        // }

                        // override fun onError(error: Exception) {
                        //     scope.launch(Dispatchers.Main) {
                        //         completionListener(false, "音频处理错误: ${error.message ?: "未知错误"}")
                        //     }
                        // }

                // 3. 初始化ExoPlayer（Media3中的ExoPlayer）
                // 使用最新Media3 API创建ExoPlayer
                    // 使用正确的API创建ExoPlayer并设置音频接收器
                    // 创建ExoPlayer实例
                      exoPlayer = ExoPlayer.Builder(context)
                          .setTrackSelector(trackSelector)
                          .build()

                // 4. 配置媒体源
                val dataSourceFactory = DefaultDataSourceFactory(context, "user-agent")
                // 使用dataSourceFactory创建MediaSourceFactory
                val mediaSourceFactory = DefaultMediaSourceFactory(dataSourceFactory as DataSource.Factory)
                exoPlayer?.setMediaSource(
                    mediaSourceFactory.createMediaSource(
                        MediaItem.fromUri(Uri.fromFile(inputFile))
                    )
                )
                exoPlayer?.prepare()

                // 等待播放器就绪
                val isReady = suspendCancellableCoroutine<Boolean> { continuation ->
                    val checkJob = scope.launch(Dispatchers.IO) {
                        var waitTime = 0
                        while (exoPlayer?.playbackState != ExoPlayer.STATE_READY) {
                            if (isCancelled) {
                                continuation.resume(false)
                                return@launch
                            }
                            Thread.sleep(100)
                            waitTime += 100
                            if (waitTime > 10000) { // 10秒超时
                                continuation.resume(false)
                                return@launch
                            }
                        }
                        continuation.resume(true)
                    }
                    continuation.invokeOnCancellation { checkJob.cancel() }
                }

                if (!isReady || isCancelled) {
                    cleanup()
                    withContext(Dispatchers.Main) {
                        completionListener(false, "准备超时或已取消")
                    }
                    return@launch
                }

                // 获取音频轨道格式
                val mediaItem = exoPlayer?.currentMediaItem
                val trackGroups = exoPlayer?.currentTrackGroups
                if (trackGroups != null && trackGroups.length > 0) {
                    for (i in 0 until trackGroups.length) {
                        val trackGroup = trackGroups.get(i)
                        for (j in 0 until trackGroup.length) {
                            if (trackGroup.type == C.TRACK_TYPE_AUDIO) {
                                // 选择第一个音频轨道
                                audioFormat = MediaFormat.createAudioFormat(
                                    outputFormat.mimeType,
                                    44100,
                                    2
                                )
                                break
                            }
                        }
                    }
                }

                // 初始化MediaMuxer并添加音频轨道
                mediaMuxer = MediaMuxer(outputPath, outputFormat.muxerOutputFormat)
                if (audioFormat != null) {
                    audioTrackIndex = mediaMuxer?.addTrack(audioFormat!!) ?: -1
                    mediaMuxer?.start()
                } else {
                    cleanup()
                    withContext(Dispatchers.Main) {
                        completionListener(false, "无法获取音频格式")
                    }
                    return@launch
                }

                // 进度监听
                val totalDurationMs = exoPlayer?.duration ?: 0L
                if (totalDurationMs <= 0) {
                    cleanup()
                    withContext(Dispatchers.Main) {
                        completionListener(false, "无法获取媒体时长")
                    }
                    return@launch
                }

                progressJob = scope.launch(Dispatchers.IO) {
                    var lastProgress = 0
                    while (exoPlayer?.playbackState != ExoPlayer.STATE_ENDED && !isCancelled) {
                        val currentPos = exoPlayer?.currentPosition ?: 0L
                        val progress = (currentPos.toFloat() / totalDurationMs * 100).toInt()
                            .coerceIn(0, 99)
                        if (progress > lastProgress) {
                            lastProgress = progress
                            withContext(Dispatchers.Main) {
                                progressListener(progress)
                            }
                        }
                        Thread.sleep(300)
                    }
                }

                // 开始提取（播放即提取）
                exoPlayer?.playWhenReady = true

                // 等待提取完成
                suspendCancellableCoroutine<Unit> { continuation ->
                    val checkJob = scope.launch(Dispatchers.IO) {
                        while (exoPlayer?.playbackState != ExoPlayer.STATE_ENDED && !isCancelled) {
                            Thread.sleep(500)
                        }
                        if (isCancelled) {
                            continuation.resumeWithException(IllegalStateException("已取消"))
                        } else {
                            continuation.resume(Unit)
                        }
                    }
                    continuation.invokeOnCancellation { checkJob.cancel() }
                }

            } catch (e: Exception) {
                Log.e(TAG, "提取失败", e)
                withContext(Dispatchers.Main) {
                    completionListener(false, "错误: ${e.message ?: "未知错误"}")
                }
                if (outputFile.exists()) outputFile.delete()
            } finally {
                cleanup()
            }
        }
    }

    /**
     * 资源清理
     */
    private fun cleanup() {
        isCancelled = true
        progressJob?.cancel()
        exoPlayer?.stop()
        exoPlayer?.release()
        exoPlayer = null
        try {
            mediaMuxer?.stop()
        } catch (e: Exception) {
            Log.w(TAG, "MediaMuxer停止失败", e)
        }
        mediaMuxer?.release()
        mediaMuxer = null
        audioTrackIndex = -1
        audioFormat = null
    }

    /**
     * 取消提取任务
     */
    fun cancel() {
        isCancelled = true
    }
}
